package helper;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.util.Map;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;

import com.frame.common.util.ClassUtils;
import com.frame.common.util.DateUtils;
import com.youxigu.common.utils.VelocityUtil;

//import com.hotshop.util.ClassUtils;
//import com.hotshop.util.DateUtils;
//import com.hotshop.util.db.FieldUtils;
//import com.youxigu.common.utils.VelocityUtil;

/**
 * 
 * @author alex.lee at 2010-9-15 上午11:03:24
 * 
 *         desc：
 * 
 */
public class AutoCoder {

	private static AutoCoder autoCoder = null;

	private String driverClassName;

	private String url;

	private String password;

	private String username;

	public String rootPackage;

	public String author;

	public String email;

	private AutoCoder() {
	}

	//初始化
	public static AutoCoder getInstance() {
		if (autoCoder == null)
			autoCoder = new AutoCoder();
		return autoCoder;
	}

	//初始化数据库连接参数
	public void setDatabaseInfo(String driverClassName, String url, String username, String password) {
		this.driverClassName = driverClassName;
		this.url = url;
		this.username = username;
		this.password = password;
	}

	//获得表字段
	private Map<String, String>[] getTableFields(String table) {
		return FieldUtils.getTableFieldMap(table, driverClassName, url, username, password);
	}

	//用来生成JAVA代码
	public boolean code(String tableName, String chineseName, String[] packageName, String[] filePath, String vmPath, String[] vm, String subPackageName) throws Exception {
		if (tableName == null || packageName == null || filePath == null || vm == null) {
			throw new Exception("tableName, packageName, vm or  filePath is empty.");
		}
		if (packageName.length != filePath.length) {
			throw new Exception("packageName'length is not equal filePath'length.");
		}

		if (rootPackage == null)
			rootPackage = ClassUtils.getRootPackage(packageName);
		for (int i = 0; i < filePath.length; i++) {
			VelocityContext velocityContext = new VelocityContext();
			velocityContext.put("util", new ClassUtils());
			velocityContext.put("rootPackage", rootPackage);
			velocityContext.put("package", packageName[i]);
			velocityContext.put("variable", ClassUtils.getFieldFromTableName(tableName));
			velocityContext.put("date", DateUtils.getDate(""));
			velocityContext.put("upfirsttable", ClassUtils.upFirstString(tableName.toLowerCase()));
			velocityContext.put("chineseName", chineseName);
			velocityContext.put("author", author);
			velocityContext.put("email", email);
			velocityContext.put("subPackageName", subPackageName);
			

			try {
				File file = new File(filePath[i]);
				if (!file.getParentFile().exists()){
					file.getParentFile().mkdirs();
				}
				if (!file.exists()){
					file.createNewFile();
				}
				//获得velocity模板类
				Template template = VelocityUtil.getVelocityUtil(vmPath, null, null).getTemplate(vm[i]);
				OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file));
				template.merge(velocityContext, osw);
				osw.flush();
				osw.close();
				System.out.println("file path: " + filePath[i]);
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}
		}
		return true;
	}

	//用来生成XML和maper文件
	public boolean codeModelAndXml(String[] tableName, String[] packageName, String[] filePath, String vmPath, String vm) throws Exception {
		if (tableName == null || filePath == null || vm == null || tableName.length != filePath.length) {
			throw new Exception("tableName, packageName or  vm is empty, or tableName'length is not equal filePath'length.");
		}

		if (rootPackage == null)
			rootPackage = ClassUtils.getRootPackage(packageName);
		for (int i = 0; i < filePath.length; i++) {
			VelocityContext velocityContext = new VelocityContext();

			Map<String,String>[] fieldMap = getTableFields(tableName[i]);
			velocityContext.put("fields", fieldMap[0]);
			velocityContext.put("fieldComments", fieldMap[1]);
			velocityContext.put("rootPackage", rootPackage);
			velocityContext.put("table", tableName[i].toLowerCase());
			velocityContext.put("variable", ClassUtils.getFieldFromTableName(tableName[i]));
			velocityContext.put("upfirsttable", ClassUtils.upSignString("_", tableName[i].toLowerCase()));
			velocityContext.put("util", new ClassUtils());
			velocityContext.put("date", DateUtils.getDate(""));
			velocityContext.put("package", packageName[i]);
			velocityContext.put("author", author);
			velocityContext.put("email", email);

			try {
				File file = new File(filePath[i]);
				if (!file.getParentFile().exists())
					file.getParentFile().mkdirs();
				if (!file.exists())
					file.createNewFile();
				Template template = VelocityUtil.getVelocityUtil(vmPath, null, null).getTemplate(vm);
				OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file));
				template.merge(velocityContext, osw);
				osw.flush();
				osw.close();
				System.out.println("model or xml path: " + filePath[i]);
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}

		}
		return true;
	}

	
	//生成所有代码
	public boolean codeAll(String[] tableName, String[] filePath, String vmPath, String[] packageName, String[] vm, String subPackageName) throws Exception {
		if (tableName == null || tableName.length == 0 || filePath == null || packageName == null || vm == null || vmPath == null) {
			throw new Exception("tableName, packageName, filePath or vm is empty.");
		}
		if (packageName.length != filePath.length || packageName.length != vm.length) {
			throw new Exception("packageName'length or filePath'length ,packageName'length are no equal vm'length.");
		}

		for (int i = 0; i < tableName.length; i++) {
			String table = tableName[i];
			for (int j = 0; j < packageName.length; j++) {
				String pName = packageName[j];
				String vmodel = vm[j];
				String type = ".java";
				if (vmodel.toLowerCase().indexOf("model") >= 0) {
					type = ".java";
					String modelPath = filePath[j] + ClassUtils.upFirstString(table) + type;
					this.codeModelAndXml(new String[] { tableName[i] }, new String[] { pName }, new String[] { modelPath }, vmPath, vmodel);
				} else if (vmodel.toLowerCase().indexOf("mapper") >= 0) {
					type = ".java";
					String mapperPath = filePath[j] + ClassUtils.upFirstString(table) + "Mapper" + type;
					this.codeModelAndXml(new String[] { tableName[i] }, new String[] { pName }, new String[] { mapperPath }, vmPath, vmodel);
				} else if (vmodel.toLowerCase().indexOf("xml") >= 0) {
					type = ".xml";
					String xmlPath = filePath[j] + ClassUtils.upFirstString(table) + "Mapper" + type;
					this.codeModelAndXml(new String[] { tableName[i] }, new String[] { pName }, new String[] { xmlPath }, vmPath, vmodel);
				} else {
					if (vmodel.toLowerCase().indexOf("daoimpl") >= 0)
						type = "DaoImpl.java";
					else if (vmodel.toLowerCase().indexOf("dao") >= 0)
						type = "Dao.java";
					else if (vmodel.toLowerCase().indexOf("serviceimpl") >= 0)
						type = "ServiceImpl.java";
					else if (vmodel.toLowerCase().indexOf("service") >= 0)
						type = "Service.java";
					else if (vmodel.toLowerCase().indexOf("controller") >= 0)
						type = "Controller.java";
					String javaPath = filePath[j] + ClassUtils.upFirstString(table) + type;
					this.code(table, null, new String[] { pName }, new String[] { javaPath }, vmPath, new String[] { vmodel } ,subPackageName);
				}
			}

		}
		return true;
	}

	public boolean addSpringConfiger(String[] tableName, String[] packageName, String[] filePath, String vmPath, String[] vm) {
		if (tableName == null || filePath == null || vm == null || vm.length != filePath.length)
			return false;

		for (int j = 0; j < vm.length; j++) {
			File file = new File(filePath[j]);
			if (!file.exists()) {
				System.err.println("message:" + filePath[j] + "文件不存在!");
				return false;
			}

			BufferedReader br = null;
			BufferedWriter bw = null;
			File tmpfile = null;
			try {
				tmpfile = File.createTempFile(file.getName(), null);
			} catch (IOException e2) {
				e2.printStackTrace();
			}
			File bakfile = new File(filePath[j] + ".bak");
			if (bakfile.exists())
				bakfile.delete();
			try {
				br = new BufferedReader(new FileReader(file));
				bw = new BufferedWriter(new FileWriter(tmpfile));
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}

			String line = null;
			try {
				while ((line = br.readLine()) != null) {
					bw.write(line);
					bw.newLine();
					// System.out.println(line);
					if (line.indexOf("</beans>") >= 0) {
						for (int i = 0; i < tableName.length; i++) {
							String content = getVelocityString(tableName[i], packageName[j], vmPath, vm[j]);
							bw.write(content);
							bw.newLine();
							// System.out.println(content);
						}
					}
					if (line.indexOf("<sqlMap resource") > 0) {
						for (int i = 0; i < tableName.length; i++) {
							String content = getVelocityString(tableName[i], packageName[j], vmPath, vm[j]);
							bw.write(content);
							bw.newLine();
							// System.out.println(content);
						}
					}
				}
				bw.flush();
				bw.close();
				br.close();
				file.renameTo(bakfile);
				tmpfile.renameTo(file);
				// tmpfile.delete();
			} catch (IOException e1) {
				e1.printStackTrace();
				return false;
			}
		}
		return true;
	}

	public boolean createSpringConfiger(String[] tableName, String[] packageName, String[] filePath, String vmPath, String[] vm) {
		if (tableName == null || filePath == null || vm == null || vm.length != filePath.length || vm.length != packageName.length) {
			System.err.println("参数不正确!");
			return false;
		}

		for (int j = 0; j < vm.length; j++) {
			VelocityContext velocityContext = new VelocityContext();
			velocityContext.put("table", tableName);
			velocityContext.put("table", tableName);
			velocityContext.put("package", packageName[j]);
			velocityContext.put("util", new ClassUtils());
			try {
				File file = new File(filePath[j]);
				if (!file.getParentFile().exists())
					file.getParentFile().mkdirs();
				if (!file.exists())
					file.createNewFile();
				Template template = VelocityUtil.getVelocityUtil(vmPath, null, null).getTemplate(vm[j]);
				OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file));
				template.merge(velocityContext, osw);
				osw.flush();
				osw.close();
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}
		}
		return true;
	}

	private String getVelocityString(String tableName, String packageName, String vmPath, String vm) {
		String content = null;
		VelocityContext velocityContext = new VelocityContext();
		velocityContext.put("table", tableName);
		velocityContext.put("package", packageName);
		velocityContext.put("upfirsttable", ClassUtils.upFirstString(tableName));
		velocityContext.put("variable", ClassUtils.getFieldFromTableName(tableName));
		velocityContext.put("util", new ClassUtils());
		Template template = null;
		StringWriter stringWriter = new StringWriter();
		try {
			template = VelocityUtil.getVelocityUtil(vmPath, null, null).getTemplate(vm);
			template.merge(velocityContext, stringWriter);
			content = stringWriter.toString();
			stringWriter.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return content;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public void setRootPcakage(String rootPackage) {
		this.rootPackage = rootPackage;
	}

	public void setEmail(String email) {
		this.email = email;
	}
}
